package com.sky.base.aspect;

import com.alibaba.fastjson2.JSON;
import com.sky.base.annotation.LogOperation;
import com.sky.base.constant.DataStatus;
import com.sky.base.security.pojo.LoginUser;
import com.sky.model.SysLogOperation;
import com.sky.service.SysLogOperationService;
import com.sky.utils.IpUtils;
import com.sky.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 操作日志，切面处理类
 * @author 尹稳健~
 * @version 1.0
 * @time 2022/9/5
 */
@Aspect
@Component
@Slf4j
public class LogOperationAspect {

    @Autowired
    private SysLogOperationService sysLogOperationService;

    /** 切入点 */
    @Pointcut("@annotation(com.sky.base.annotation.LogOperation)")
    public void logPointCut(){}

    /** 通知处理 */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        long beginTime = System.currentTimeMillis();
        try {
            // 调用目标方法，不写point.proceed()，方法不会调用,将结果返回
            Object result = point.proceed();

            // 计算执行时长
            long time = System.currentTimeMillis() - beginTime;

            // 保存日志
            saveLog(point,time, DataStatus.NORMAL);

            return result;
        } catch (Exception e) {
            // 计算执行时长(毫秒)
            long time = System.currentTimeMillis() - beginTime;
            // 保存日志
            saveLog(point,time, DataStatus.REMOVE);

            throw e;
        }

    }

    // 保存日志
    public void saveLog(ProceedingJoinPoint joinPoint, long time, Short status) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(),signature.getParameterTypes());
        LogOperation annotation = method.getAnnotation(LogOperation.class);
        // 获取操作日志对象
        Class<SysLogOperation> sysLogOperationClass = SysLogOperation.class;
        SysLogOperation sysLogOperation = sysLogOperationClass.newInstance();
        if (!Objects.isNull(annotation)){
            sysLogOperation.setOperation(annotation.value());
        }
        // 获取当前登录用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        sysLogOperation.setUsername(loginUser.getUser().getUsername());
        sysLogOperation.setRequestTime((int) time);
        sysLogOperation.setStatus(status);
        sysLogOperation.setCreateId(loginUser.getUser().getId());
        sysLogOperation.setUpdateId(loginUser.getUser().getId());
        sysLogOperation.setCreateTime(LocalDateTime.now());
        sysLogOperation.setUpdateTime(LocalDateTime.now());
        HttpServletRequest request = ServletUtils.getRequest();
        sysLogOperation.setIp(IpUtils.getIpAddr(request));
        sysLogOperation.setRequestUri(request.getRequestURI());
        sysLogOperation.setRequestMethod(request.getMethod());

        // 获取参数
        Object[] args = joinPoint.getArgs();
        String params = JSON.toJSONString(args[0]);
        sysLogOperation.setRequestParams(params);

        // 保存数据
        sysLogOperationService.save(sysLogOperation);

    }


}
